package com.evoupsight.monitorpass.alarm.services;

import com.evoupsight.monitorpass.alarm.cache.FunctionCache;
import com.evoupsight.monitorpass.alarm.cache.ItemCache;
import com.evoupsight.monitorpass.alarm.cache.ServerCache;
import com.evoupsight.monitorpass.alarm.cache.TriggerCache;
import com.evoupsight.monitorpass.alarm.dao.mapper.*;
import com.evoupsight.monitorpass.alarm.dao.model.*;
import com.evoupsight.monitorpass.alarm.dto.OperationMessageDto;
import com.evoupsight.monitorpass.alarm.dto.memcache.HostTemplateDto;
import com.evoupsight.monitorpass.alarm.dto.memcache.TriggerDto;
import com.evoupsight.monitorpass.alarm.dto.opentsdb.QueryDto;
import com.evoupsight.monitorpass.alarm.exporession.MainVisitor;
import com.evoupsight.monitorpass.alarm.exporession.TriggerLexer;
import com.evoupsight.monitorpass.alarm.exporession.TriggerParser;
import com.geneea.celery.Celery;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;
import org.opentsdb.client.PoolingHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.evoupsight.monitorpass.alarm.constants.Constants.*;
import static com.evoupsight.monitorpass.alarm.constants.Constants.ServerStatus.NOT_MONITORING;
import static com.evoupsight.monitorpass.alarm.constants.RedisConstants.KEY_EXPRESSION_STATUS_KEY_PREFIX;
import static com.evoupsight.monitorpass.alarm.constants.RedisConstants.KEY_PREFIX_OPERATION;
import static com.evoupsight.monitorpass.alarm.util.ExpressionUtil.antlrTrueFalse;


/**
 * @author evoup
 */
@SuppressWarnings({"Duplicates", "SpringJavaAutowiredFieldsWarningInspection", "SpringJavaInjectionPointsAutowiringInspection"})
@Service
public class ScanService {
    private static final Logger LOG = LoggerFactory.getLogger(ScanService.class);
    @Value("${opentsdb.serverurl}")
    private String opentsdbUrl;

    private final Configuration hbaseConf;

    private final JedisPool jedisPool;

    private final PoolingHttpClient httpClient;

    private final Celery celeryClient;

    @Autowired
    private ScanService(JedisPool jedisPool, Configuration hbaseConf, PoolingHttpClient httpClient, Celery celeryClient) {
        this.jedisPool = jedisPool;
        this.hbaseConf = hbaseConf;
        this.httpClient = httpClient;
        this.celeryClient = celeryClient;
    }

    @Autowired
    private TriggerCache triggerCache;
    @Autowired
    private ServerCache serverCache;
    @Autowired
    private FunctionCache functionCache;
    @Autowired
    private ItemCache itemCache;
    @Autowired
    private RelationServerServerGroupMapper relationServerServerGroupMapper;
    @Autowired
    private RelationTemplateServerGroupMapper relationTemplateServerGroupMapper;
    @Autowired
    private EventMapper eventMapper;
    @Autowired
    private FunctionMapper functionMapper;
    @Autowired
    private ServerMapper serverMapper;

    /**
     * 执行所有工作
     */
    void doAllJobs() {
        // TODO写入扫描时间

        checkHosts();
    }

    /**
     * 保存上次扫描时间(Hbase中，已经没用了)
     *
     * @throws IOException 异常
     */
    @Deprecated
    private void saveHBaseLastScanTime() throws IOException {
        LOG.debug("save scan time");
        try (Connection connection = ConnectionFactory.createConnection(hbaseConf);
             Table table = connection.getTable(TableName.valueOf(MDB_TAB_ENGINE))) {
            Put p = new Put(Bytes.toBytes(KEY_SCAN_DURATION));
            p.addColumn(Bytes.toBytes("scan"), Bytes.toBytes("duration"), Bytes.toBytes(System.currentTimeMillis()));
            table.put(p);
        }
    }


    /**
     * 检查主机
     */
    private void checkHosts() {
        // server -> server_group -> template -> trigger -> function -> 计算function数值 -> 返回function表达式 -> 判断真假
        List<Server> servers = serverCache.fetchAllMonitoringed();
        servers.stream().filter(Objects::nonNull).filter(s -> !new Integer(NOT_MONITORING.ordinal()).equals(s.getStatus())).forEach(s -> {
            RelationServerServerGroupExample example = new RelationServerServerGroupExample();
            example.createCriteria().andServerIdEqualTo(s.getId());
            List<RelationServerServerGroup> relationServerServerGroups = relationServerServerGroupMapper.selectByExample(example);
            if (CollectionUtils.isNotEmpty(relationServerServerGroups)) {
                for (RelationServerServerGroup relation : relationServerServerGroups) {
                    if (s.getId().equals(relation.getServerId())) {
                        Integer servergroupId = relation.getServergroupId();
                        RelationTemplateServerGroupExample example1 = new RelationTemplateServerGroupExample();
                        example1.createCriteria().andServergroupIdEqualTo(servergroupId);
                        List<RelationTemplateServerGroup> relationTemplateServerGroup = relationTemplateServerGroupMapper.selectByExample(example1);
                        for (RelationTemplateServerGroup relation1 : relationTemplateServerGroup) {
                            Long templateId = relation1.getTemplateId();
                            List<Trigger> triggers = triggerCache.getByTemplate(templateId);
                            if (CollectionUtils.isNotEmpty(triggers)) {
                                for (Trigger trigger : triggers) {
                                    String expression = trigger.getExpression();
                                    // 找出表达式中的function，进行演算
                                    Pattern p = Pattern.compile("\\{([^}]*)\\}");
                                    Matcher m = p.matcher(expression);
                                    StringBuffer sb = new StringBuffer();
                                    String tsdbValue = "";
                                    while (m.find()) {
                                        // 获取时序数据库中的数据，如果已经挂了，就持久化一下，这样前端就显示宕机了
                                        tsdbValue = getOpentsdbValue(m.group(1), s, trigger);
                                        m.appendReplacement(sb, tsdbValue);
                                    }
                                    m.appendTail(sb);
                                    LOG.info("key是：" + trigger.getExpression());
                                    LOG.info("最终表达式是：" + sb.toString() + " tsdbValue:" + tsdbValue);
                                    if (antlrTrueFalse(sb.toString())) {
                                        LOG.warn("条件成立，进入事件逻辑");
                                        // 问题事件生成
                                        generateProblemEvent(trigger);
                                        // 进行操作
                                        doOperation(trigger, s, tsdbValue);
                                        LOG.info("tsdbValues:" + tsdbValue);
                                        try (Jedis resource = jedisPool.getResource()) {
                                            resource.setex(KEY_EXPRESSION_STATUS_KEY_PREFIX + expression, 259200, String.valueOf(ExpressionState.TRUE.ordinal()));
                                        } catch (Exception e) {
                                            LOG.error(e.getMessage(), e);
                                        }
                                        LOG.info("问题事件逻辑结束");
                                    } else {
                                        // 如果问题恢复，需要生成一条恢复的事件，根据是否发送通知，可以发企业微信消息或邮件通知
                                        try (Jedis resource = jedisPool.getResource()) {
                                            String prevStatus = resource.get(KEY_EXPRESSION_STATUS_KEY_PREFIX + expression);
                                            if (String.valueOf(ExpressionState.TRUE.ordinal()).equals(prevStatus)) {
                                                generateRecoveryEvent(trigger);
                                                resource.setex(KEY_EXPRESSION_STATUS_KEY_PREFIX + expression, 259200, String.valueOf(ExpressionState.FALSE.ordinal()));
                                                LOG.info("生成恢复正常的事件");
                                            }
                                        } catch (Exception e) {
                                            LOG.error(e.getMessage(), e);
                                        }

                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
    }

    /**
     * 处理问题事件
     *
     * @param trigger
     */
    private void generateProblemEvent(Trigger trigger) {
        // 选择最近的一条事件记录
        // 1.如果不存在事件，则生成事件
        // 2.如果存在事件，事件状态发生变化，则新建事件
        // 3.如果存在事件，事件已经恢复，则新建事件(是2的特列)
        // 4.是否有必要有一个缓冲时间
        List<Event> events = eventMapper.selectByExample(
                new EventExample().limit(1).createCriteria().andTargetIdEqualTo(trigger.getId().intValue())
                        .example().orderBy(Event.Column.time.desc())
        );
        if (CollectionUtils.isEmpty(events)) {
            Event event = Event.builder().event("").time(new Long(System.currentTimeMillis() / 1000).intValue()).acknowledged(false).targetId(trigger.getId().intValue()).type(EventState.PROBLEM.ordinal()).build();
            eventMapper.insertSelective(event);
        } else if (new Integer(EventState.OK.ordinal()).equals(events.get(0).getType())) {
            Event event = Event.builder().event("").time(new Long(System.currentTimeMillis() / 1000).intValue()).acknowledged(false).targetId(trigger.getId().intValue()).type(EventState.PROBLEM.ordinal()).build();
            eventMapper.insertSelective(event);
        }
    }

    /**
     * 生成恢复事件
     *
     * @param trigger
     */
    private void generateRecoveryEvent(Trigger trigger) {
        Event event = Event.builder().event("").time(new Long(System.currentTimeMillis() / 1000).intValue()).acknowledged(false).targetId(trigger.getId().intValue()).type(EventState.OK.ordinal()).build();
        eventMapper.insertSelective(event);
    }


    /**
     * 获取trigger的详情,主机是什么，对应的事件描述
     *
     * @param trigger
     */
    private OperationMessageDto getTriggerDetail(Trigger trigger) {
//        function = Function.objects.filter(id=obj.target_id).get()
        FunctionExample functionExample = new FunctionExample();
        functionExample.createCriteria().andTriggerIdEqualTo(trigger.getId());
        List<Function> functions = functionMapper.selectByExample(functionExample);
        if (CollectionUtils.isNotEmpty(functions)) {
            Function function = functions.get(0);
//            host_id = function.item.host_id
            // 找函数对应的监控项的主机
            if (function != null && function.getId() != null) {
                Item item = itemCache.get(function.getItemId());
                if (item != null && item.getHostId() != null) {
                    Server server = serverMapper.selectByPrimaryKey(item.getHostId());
                    if (server != null) {
                        return OperationMessageDto.builder().serverId(server.getId()).serverName(server.getName()).itemName(item.getName())
                                .triggerName(trigger.getName()).build();
                    }
                }
            }
        }
        return null;
    }

    /**
     * 进行操作，发送消息，执行命令
     */
    private void doOperation(Trigger trigger, Server server, String itemValue) {
        // 从redis中查询处理操作
        // 轮次的确定：如果没有数据，插入就是第一轮， key为triggerId,value为轮次和剩余的时间（格式为1|now+3600），并且触发操作
        //           如果有数据，取出value，判断本轮次是否已经结束，如果结束就加轮次，并且触发操作
        String key = String.format(KEY_PREFIX_OPERATION, trigger.getId());
        try (Jedis resource = jedisPool.getResource()) {
            String value = resource.get(key);
            int interval = 3600;
            if (StringUtils.isEmpty(value)) {
                value = String.format("1|%s", System.currentTimeMillis() / 1000 + interval);
                resource.set(key, value);
                // 触发操作
                LOG.warn("触发操作:" + server.getName());
                OperationMessageDto triggerDetail = getTriggerDetail(trigger);
                LOG.warn("triggerDetail" + new Gson().toJson(triggerDetail));
                if (triggerDetail != null && StringUtils.isNotEmpty(triggerDetail.getTriggerName())) {
                    // 替换变量的对应值
                    String detail = triggerDetail.getTriggerName().replace("{HOST.NAME}", triggerDetail.getServerName());
                    celeryClient.submit("tasks.send_wechat_message", new Object[]{triggerDetail.getServerName(), triggerDetail.getItemName(), detail, itemValue, new DateTime().toString("yyyy-MM-dd HH:mm:ss"), trigger.getId()});
                }
            } else {
                String[] split = value.split("\\|");
                if (split.length == 2) {
                    int turn = Integer.parseInt(split[0]);
                    // 不让数值过大
                    if (turn > 9999) {
                        turn = 9999;
                    }
                    Integer ts = Integer.valueOf(split[1]);
                    if (System.currentTimeMillis() / 1000 - ts > 0) {
                        // 迭代轮次，并触发操作
                        value = String.format("%s|%s", turn + 1, System.currentTimeMillis() / 1000 + interval);
                        resource.set(key, value);
                        // 触发操作
                        LOG.warn("触发操作:" + server.getName());
                        OperationMessageDto triggerDetail = getTriggerDetail(trigger);
                        LOG.warn("triggerDetail" + new Gson().toJson(triggerDetail));
                        if (triggerDetail != null && StringUtils.isNotEmpty(triggerDetail.getTriggerName())) {
                            // 替换变量的对应值
                            String detail = triggerDetail.getTriggerName().replace("{HOST.NAME}", triggerDetail.getServerName());
                            celeryClient.submit("tasks.send_wechat_message", new Object[]{triggerDetail.getServerName(), triggerDetail.getItemName(), detail, itemValue, new DateTime().toString("yyyy-MM-dd HH:mm:ss"), trigger.getId()});
                        }
                    }
                }
            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }

    /**
     * 返回opentsdb的数值
     */
    private String getOpentsdbValue(String functionId, Server m, Trigger trigger) {
        // TODO 实现其他function的具体参数
        LOG.info("functionId:" + functionId);
        Function f = functionCache.get(new Long(functionId));
        OperationMessageDto triggerDetail = getTriggerDetail(trigger);
        if (f != null && triggerDetail != null && StringUtils.isNotEmpty(triggerDetail.getServerName())) {
            // f.name = 'avg'  f.parameter = '5m'
            PeriodFormatter formatter = new PeriodFormatterBuilder()
                    .appendDays().appendSuffix("d ")
                    .appendHours().appendSuffix("h ")
                    .appendMinutes().appendSuffix("m")
                    .toFormatter();
            Period period = null;
            try {
                period = formatter.parsePeriod(f.getParameter());
            } catch (Exception e) {
                LOG.warn(f.getParameter() + "不是时间参数");
            }
            // 获取监控项的数值
            Integer itemId = f.getItemId();
            Item item = itemCache.get(itemId);
            HttpGet httpGet;
            HttpResponse httpResponse = null;
            try {
                String key = item.getKey();
                String apiUrl = opentsdbUrl + "/api/query?start=15m-ago&m=sum:apps.backend." + triggerDetail.getServerName() + "." + key;
                LOG.info("tsdb apiUrl:" + apiUrl);
                httpGet = new HttpGet(apiUrl);
                httpResponse = httpClient.execute(httpGet);
                if (httpResponse != null && httpResponse.getStatusLine().getStatusCode() == 200) {
                    HttpEntity entity = httpResponse.getEntity();
                    // 将entity当中的数据转换为字符串
                    String response = EntityUtils.toString(entity, "utf-8");
                    ArrayList<QueryDto> queryDtos = new Gson().fromJson(response, new TypeToken<ArrayList<QueryDto>>() {
                    }.getType());
                    if (queryDtos != null && queryDtos.size() > 0 && queryDtos.get(0).getDps() != null && queryDtos.get(0).getDps().size() > 0) {
                        HashMap<String, Object> dataPoints = queryDtos.get(0).getDps();
                        for (Map.Entry<String, Object> ignored : dataPoints.entrySet()) {
                            // 在线
                            serverCache.makeUp(triggerDetail.getServerId());
                            break;
                        }

                        TreeMap<String, Object> treeMap = new TreeMap<>(dataPoints);
                        ArrayList<Double> primes = new ArrayList<>();
                        if (treeMap.size() != 0 && period != null) {
                            // 确定结束时间
                            Integer lastTimeKey = Integer.valueOf(treeMap.lastEntry().getKey());
                            // 确定起始时间
                            Integer startTime = lastTimeKey - period.getSeconds();
                            for (Map.Entry<String, Object> entry : dataPoints.entrySet()) {
                                Integer ts = Integer.valueOf(entry.getKey());
                                if (ts >= startTime && ts <= lastTimeKey) {
                                    primes.add((Double) entry.getValue());
                                }
                            }
                            // 这里要开始分支先完成avg的，如果客户端做了去重，avg(5m)会出现捞不到数据的问题，所以之前获取前30m-ago的数据点
                            // 找到最后一个也就是最近的一个数据点，往前追溯5m，得到这段时间范围内的多个数据点，最后做avg。
                            // 当然，可能还是找不到，那么就用所有的数据点做avg返回。
                            // 但是，这引入了一个新的问题，就是宕机的判断可能不正确了。
                            DoubleSummaryStatistics stats = primes.stream()
                                    .mapToDouble((p) -> p)
                                    .summaryStatistics();
                            return Double.toString(Math.round(stats.getAverage() * 100.0) / 100.0);
                        }

                    } else {
                        // 宕机
                        serverCache.makeDown(triggerDetail.getServerId());
                    }
                }
            } catch (IOException e) {
                LOG.error(e.getMessage(), e);
            } finally {
                releaseResponse(httpResponse);
            }
        }
        return "";
    }

    /**
     * 返回指定trigger对应的服务器
     *
     * @param triggerId
     * @return
     */
    private List<Server> getTriggerBelongServers(Integer triggerId) {
        List<Trigger> triggers = triggerCache.fetchAll();
        Set<Server> checkServers = new HashSet<>();
        triggers.stream().filter(Objects::nonNull).filter(t -> triggerId.equals(t.getId().intValue())).forEach(x -> {
            System.out.println(x.getTemplateId());
            Long templateId = x.getTemplateId();
            List<Server> servers = serverCache.getByTemplate(templateId);
            servers.stream().filter(Objects::nonNull).forEach(checkServers::add);
        });
        checkServers.stream().filter(Objects::nonNull).forEach(s -> {
            LOG.info("server:{} will be checked", s.getName());
        });
        return new ArrayList<>(checkServers);
    }

    /**
     * 检查是否宕机
     */
    @Deprecated
    private void scanHostDownOld() {
        HttpResponse httpResponse = null;
        Gson gson = new Gson();
        try (Jedis resource = jedisPool.getResource()) {
            String value1 = resource.get("key1");
            List<HostTemplateDto> hostTemplateDtos = new Gson().fromJson(value1,
                    new TypeToken<ArrayList<HostTemplateDto>>() {
                    }.getType());
            if (hostTemplateDtos != null) {
                for (HostTemplateDto hostTemplateDto : hostTemplateDtos) {
                    String hostStatus = HOST_STATUS_DOWN;
                    String host = hostTemplateDto.getHost();
                    if (StringUtils.isNotEmpty(host)) {
                        String myhost = StringUtils.remove(host, "-");
                        String apiUrl = opentsdbUrl +
                                "/api/query?start=5m-ago&m=sum:apps.backend." + myhost +
                                ".proc.loadavg.5min%7Bhost=" + host + "%7D";
                        HttpGet httpGet = new HttpGet(apiUrl);
                        httpResponse = httpClient.execute(httpGet);
                        if (httpResponse != null && httpResponse.getStatusLine().getStatusCode() == 200) {
                            HttpEntity entity = httpResponse.getEntity();
                            //将entity当中的数据转换为字符串
                            String response = EntityUtils.toString(entity, "utf-8");
                            ArrayList<QueryDto> queryDtos = gson.fromJson(response, new TypeToken<ArrayList<QueryDto>>() {
                            }.getType());
                            if (queryDtos != null && queryDtos.size() > 0 && queryDtos.get(0).getDps() != null && queryDtos.get(0).getDps().size() > 0) {
                                hostStatus = HOST_STATUS_UP;
                            }
                        }
                    }
                    if (hostStatus.equals(HOST_STATUS_UP)) {
                        goThroughTriggers(host, hostTemplateDto.getTemplateIds());
                    }
                    // saveHbaseHostStatus(hostStatus, host);
                }
            }
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        } finally {
            releaseResponse(httpResponse);
        }
    }


    /**
     * 检查表达式
     */
    private void goThroughTriggers(String host, List<String> templateIds) {
        try (Jedis resource = jedisPool.getResource()) {
            String value = resource.get("key6");
            // key为triggerid
            HashMap<String, TriggerDto> triggerDtos = new Gson().fromJson(value,
                    new TypeToken<HashMap<String, TriggerDto>>() {
                    }.getType());
            // key为triggerid，用不到
            if (triggerDtos != null) {
                triggerDtos.forEach((triggerid, triggerinfo) -> runExpression(host, templateIds, triggerinfo));
            }
        }
    }

    /**
     * 执行表达式
     *
     * @param host            　主机名
     * @param hostTemplateIds 　主机对应的模板
     * @param trigger         　触发器
     */
    private void runExpression(String host, List<String> hostTemplateIds, TriggerDto trigger) {
        if (trigger != null && StringUtils.isNotEmpty(trigger.getHostId())) {
            if (hostTemplateIds.contains(trigger.getHostId())) {
                String myhost = StringUtils.remove(host, "-");
                LOG.info("host:{} call expression:{}", host, trigger.getExpression());
                // {13078}>5 <=> system.cpu.load[allcpu,avg1].avg(5m)>5 => proc.loadavg.1min>5
                // 例子：如果表达式为{13078}>5，视作是查询proc.loadavg.1min，函数为avg,参数为5m，就是调用
                // opentsdb的http://opentsdb2:14242/api/query?start=5m-ago&m=avg:apps.backend.evoupzhanqi.proc.loadavg.1min
                if ("{13078}>5".equals(trigger.getExpression())) {
                    HttpResponse httpResponse = null;
                    HttpGet httpGet = new HttpGet(opentsdbUrl +
                            "/api/query?start=5m-ago&m=sum:apps.backend." + myhost +
                            ".proc.loadavg.1min");
                    try {
                        httpResponse = httpClient.execute(httpGet);
                        if (httpResponse != null && httpResponse.getStatusLine().getStatusCode() == 200) {
                            HttpEntity entity = httpResponse.getEntity();
                            //将entity当中的数据转换为字符串
                            String response = EntityUtils.toString(entity, "utf-8");
                            ArrayList<QueryDto> queryDtos = new Gson().fromJson(response, new TypeToken<ArrayList<QueryDto>>() {
                            }.getType());
                            if (queryDtos != null && queryDtos.get(0).getDps() != null) {
                                List<Object> list = new ArrayList<>();
                                queryDtos.get(0).getDps().forEach((time, datapoint) -> list.add(datapoint));
                                DoubleSummaryStatistics stats = list.stream().mapToDouble((x) -> new Double(x.toString())).summaryStatistics();
                                double average = stats.getAverage();
                                LOG.info("average:" + average);
                                CharStream input = new ANTLRInputStream("{" + average + "}>0.82 AND TRUE");
                                TriggerLexer lexer = new TriggerLexer(input);
                                CommonTokenStream tokens = new CommonTokenStream(lexer);
                                TriggerParser parser = new TriggerParser(tokens);
                                ParseTree tree = parser.expr();
                                MainVisitor.Visitor eval = new MainVisitor.Visitor();
                                Object visit = eval.visit(tree);
                                LOG.info("Trigger result:" + visit);
                            }
                        }
                    } catch (IOException e) {
                        LOG.error(e.getMessage(), e);
                    } finally {
                        releaseResponse(httpResponse);
                    }
                }
            }
        }
    }


    /**
     * 保存host状态
     *
     * @param hostStatus host状态
     * @param host       　host名字
     */
    @Deprecated
    private void saveHbaseHostStatus(String hostStatus, String host) {
        try (Connection connection = ConnectionFactory.createConnection(hbaseConf);
             Table table = connection.getTable(TableName.valueOf(MDB_TAB_HOST))) {
            Put p = new Put(Bytes.toBytes(host));
            p.addColumn(Bytes.toBytes("info"), Bytes.toBytes("status"), Bytes.toBytes(hostStatus));
            table.put(p);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }


    /**
     * 清理
     *
     * @param rp 回复
     */
    private void releaseResponse(HttpResponse rp) {
        if (rp != null) {
            try {
                HttpEntity entity = rp.getEntity();
                if (entity != null) {
                    InputStream instream = entity.getContent();
                    try {
                        // do something useful
                    } finally {
                        instream.close();
                    }
                }
            } catch (Exception e) {
                LOG.error(e.getMessage(), e);
            }
        }
    }
}
